home *** CD-ROM | disk | FTP | other *** search
- (herald (back_end live)
- (env t (orbit_top defs)))
-
- ;;; Copyright (c) 1985 Yale University
- ;;; Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
- ;;; This material was developed by the T Project at the Yale University Computer
- ;;; Science Department. Permission to copy this software, to redistribute it,
- ;;; and to use it for any purpose is granted, subject to the following restric-
- ;;; tions and understandings.
- ;;; 1. Any copy made of this software must include this copyright notice in full.
- ;;; 2. Users of this software agree to make their best efforts (a) to return
- ;;; to the T Project at Yale any improvements or extensions that they make,
- ;;; so that these may be included in future releases; and (b) to inform
- ;;; the T Project of noteworthy uses of this software.
- ;;; 3. All materials developed as a consequence of the use of this software
- ;;; shall duly acknowledge such use, in accordance with the usual standards
- ;;; of acknowledging credit in academic research.
- ;;; 4. Yale has made no warrantee or representation that the operation of
- ;;; this software will be error-free, and Yale is under no obligation to
- ;;; provide any services, by way of maintenance, update, or otherwise.
- ;;; 5. In conjunction with products arising from the use of this material,
- ;;; there shall be no use of the name of the Yale University nor of any
- ;;; adaptation thereof in any advertising, promotional, or sales literature
- ;;; without prior written consent from Yale in each case.
- ;;;
-
- ;;; Copyright (c) 1985 David Kranz
-
-
- (define (analyze top-node)
- (analyze-top top-node)
- (live-analyze-top top-node)
- (collect-top top-node)
- (call-analyze-top top-node)
- (bind ((*noise-flag* t))
- (print-variable-info *unit-variables*))
- ; (type-analyze-top top-node)
- ; (rep-analyze-top top-node)
- (hoist-continuations (lambda-body top-node))
- (close-analyze-top top-node nil))
-
- (define (vframe-or-ezclose master)
- (cond ((constant-continuation? master)
- 'ezclose)
- (else 'label)))
-
- ;;; Live variable analysis
-
- (define (live-analyze-top node)
- (live-analyze (car (call-args (lambda-body node)))))
-
-
- (define (live-analyze node)
- (cond ((lambda-node? node)
- (if (labels-master-lambda? node)
- (live-analyze-y node)
- (live-analyze-lambda node)))
- ((leaf-node? node)
- (live-analyze-leaf node))
- (else
- (bug "live-analyze called on a call-node ~S" node))))
-
- (define (live-analyze-lambda node)
- (receive (live global? known) (live-analyze-body (lambda-body node))
- (let* ((live-1 (set-difference live (lambda-all-variables node)))
- (live (if (neq? (node-role node) call-proc) ;; Let
- live-1
- (set-difference live-1 (map (lambda (node)
- (and (lambda-node? node)
- (lambda-self-var node)))
- (call-args (node-parent node)))))))
- (set (lambda-live node) live)
- (select (lambda-strategy node)
- ((strategy/heap)
- (walk change-to-heap known)
- (cond ((and (null? live) (not (known-lambda? node)))
- (set (lambda-env node) 'unit-internal-closure)
- (return live t known))
- (global?
- (set (lambda-env node) 'unit-internal-template)
- (return live t known))
- (else
- (set (lambda-env node) nil)
- (return live nil known))))
- ((strategy/label)
- (cond ((fully-recursive? node)
- (walk change-to-vframe-or-heap known)
- (cond ((memq? node known))
- ((not (let-lambda? node))
- (change-to-vframe-or-heap node))
- ((fx>= (fx+ (length (lambda-live node))
- (length (lambda-variables node)))
- *argument-registers*)
- (set (lambda-strategy node) strategy/heap)))))
- (set (lambda-env node) (if global? 'needs-link '#f))
- (return live global? known))
- ((strategy/stack)
- (set (lambda-env node) (if global? 'needs-link '#f))
- (walk (lambda (l)
- (if (fully-recursive? l)
- (change-to-heap l)))
- known)
- (return live global? known))
- (else
- (return live global? known))))))
-
-
-
- (define (change-to-vframe-or-heap l)
- (if (and (neq? (lambda-strategy l) strategy/heap)
- (fx>= (fx+ (length (lambda-live l)) (length (lambda-variables l)))
- *argument-registers*))
- (set-label-strategies
- (node-parent (node-parent l))
- strategy/heap)))
-
-
- (define (change-to-heap l)
- (if (not (fx<= (length (lambda-live l)) 2))
- (set-label-strategies (node-parent (node-parent l))
- strategy/heap)))
-
-
- (define (set-label-strategies node strategy)
- (walk (lambda (l) (set (lambda-strategy l) strategy))
- (cdr (call-args (lambda-body node))))
- (set (lambda-strategy node) strategy))
-
-
- (define (live-analyze-leaf node)
- (cond ((literal-node? node)
- (cond ((or (addressable? (leaf-value node))
- (primop? (leaf-value node)))
- (return '() nil '()))
- (else
- (return '() t '()))))
- ((primop-node? node)
- (cond ((foreign-name (primop-value node))
- (return '() t '()))
- (else
- (return '() nil '()))))
- ((variable-known (reference-variable node))
- => (lambda (label)
- (select (lambda-strategy label)
- ((strategy/label)
- (return (lambda-live label)
- (eq? (lambda-env label) 'needs-link)
- (if (labels-lambda? label)
- (list label)
- '())))
- ((strategy/stack)
- (return '() nil '()))
- (else
- (if (eq? (lambda-env label) 'unit-internal-closure)
- (return '() t '())
- (return `(,(lambda-self-var label)) nil '()))))))
- ((bound-to-continuation? (reference-variable node))
- (return '() nil '()))
- ((variable-binder (reference-variable node))
- (return `(,(reference-variable node)) nil '()))
- (else
- (return '() t '()))))
-
- (define (known-lambda? node)
- (let ((p (node-parent (node-parent node))))
- (cond ((node-parent p)
- => (lambda (p)
- (and (primop-node? (call-proc p))
- (eq? (primop-value (call-proc p)) primop/Y))))
- (else nil))))
-
-
- (define (live-analyze-body node)
- (iterate loop ((args (if (lambda-node? (call-proc node))
- (reverse (call-proc+args node)) ; let lambda last!
- (call-proc+args node)))
- (live '())
- (global? nil)
- (known '()))
- (cond (args
- (receive (vars gl? kn) (live-analyze (car args))
- (loop (cdr args)
- (union vars live)
- (or global? gl?)
- (union kn known))))
- ((call-hoisted-cont node)
- => (lambda (l)
- (return (union live (lambda-live l))
- (or global? (eq? (lambda-env l) 'needs-link))
- known)))
- (else
- (return live global? known)))))
-
-
- (define (live-analyze-Y master)
- (if (and (not (lambda-db master))
- (eq? (lambda-strategy master) strategy/label))
- (set (lambda-db master) (vframe-or-ezclose master)))
- (destructure (((body-expr . label-exprs) (call-args (lambda-body master)))
- (strategy (lambda-strategy master)))
- (receive (global? known) (set-label-live label-exprs)
- (receive (l gl? kn) (live-analyze-lambda body-expr)
- (if (neq? (lambda-strategy master) strategy)
- (live-analyze-y master)
- (do ((exprs label-exprs (cdr exprs))
- (live l (union live (lambda-live (car exprs)))))
- ((null? exprs)
- (return (set-difference (delq! (lambda-self-var master) live)
- (map lambda-self-var label-exprs))
- (or global? gl?)
- (set-difference (union known kn) label-exprs)))))))))
-
-
-
- (define (set-label-live label-exprs)
- (iterate again ()
- (iterate loop ((lambdas label-exprs)
- (changed? nil)
- (global? nil)
- (known '()))
- (cond ((not (null? lambdas))
- (let ((old-live (lambda-live (car lambdas)))
- (old-global? (true? (lambda-env (car lambdas)))))
- (receive (live gl? kn) (live-analyze-lambda (car lambdas))
- (cond ((and (set-eq? old-live live)
- (eq? gl? old-global?))
- (loop (cdr lambdas)
- changed?
- (or global? gl?)
- (union kn known)))
- (else
- (loop (cdr lambdas)
- t
- (or global? gl?)
- (union kn known)))))))
- (changed?
- (again))
- (else
- (return global? known))))))
-
- (define (hoist-continuation cont)
- (let* ((call (node-parent cont))
- (live (hack-live (lambda-live cont) call)))
- (iterate loop ((call call))
- (let ((l (node-parent call)))
- (cond ((or (primop-ref? (call-proc (node-parent l))
- primop/remove-state-object)
- (neq? (lambda-strategy l) strategy/open)
- (intersection? (lambda-variables l) live)
- (eq? (node-role l) call-proc)
- (fxn= (call-exits (node-parent l)) 1))
- (set (call-hoisted-cont call) cont))
- (else
- (loop (node-parent l))))))))
-
- (define (hack-live live call)
- (do ((args (cdr (call-args call)) (cdr args))
- (live live (if (and (lambda-node? (car args))
- (eq? (lambda-strategy (car args)) strategy/hack))
- (union live (lambda-live (car args)))
- live)))
- ((null? args) live)))
-
-
- (define (collect-top node)
- (set *unit-literals* '())
- (set *unit-variables* '())
- (collect (car (call-args (lambda-body node)))))
-
- (define (collect node)
- (cond ((lambda-node? node)
- (walk collect (call-proc+args (lambda-body node))))
- ((literal-node? node)
- (let ((lit (literal-value node)))
- (or (addressable? lit)
- (primop? lit)
- (memq? lit *unit-literals*)
- (push *unit-literals* lit))))
- ((primop-node? node)
- (let ((prim (primop-value node)))
- (and (foreign-name prim)
- (not (memq? prim *unit-literals*))
- (push *unit-literals* prim))))
- (else
- (let ((var (reference-variable node)))
- (or (variable-binder var)
- (memq? var *unit-variables*)
- (push *unit-variables* var))))))
-
-
- (define (hoist-continuations node)
- (let ((do-children (lambda (arg)
- (and (lambda-node? arg)
- (hoist-continuations (lambda-body arg))))))
- (case (call-exits node)
- ((1)
- (destructure (((proc cont . args) (call-proc+args node)))
- (cond ((lambda-node? proc)
- (walk do-children (call-proc+args node))
- nil)
- ((leaf-node? cont) (walk do-children args) nil)
- (else
- (xselect (lambda-strategy cont)
- ((strategy/open strategy/label)
- (let ((c (hoist-continuations (lambda-body cont))))
- (set (call-hoisted-cont node) c)
- c))
- ((strategy/stack)
- (do-children cont)
- (set (call-hoisted-cont node) cont)))
- (walk do-children args)
- (call-hoisted-cont node)))))
- (else
- (walk do-children (call-proc+args node))
- nil))))
-
- (define-constant call-below? node-instructions)
- (define-constant call-below/never 0)
- (define-constant call-below/maybe 1)
- (define-constant call-below/definitely 2)
-
-
- (define (call-analyze-top node)
- (call-analyze (lambda-body node)))
-
-
-
- (define (call-analyze-leaf node)
- (cond ((lambda-node? node)
- (let ((call-below? (call-analyze (lambda-body node))))
- (select (lambda-strategy node)
- ((strategy/stack) call-below/definitely)
- ((strategy/heap) call-below/never)
- (else call-below?))))
- (else
- call-below/never)))
-
- (define (call-analyze node)
- (let ((below?
- (case (call-exits node)
- ((0)
- (cond ((lambda-node? (call-proc node))
- (call-analyze-let node))
- (else
- (walk call-analyze-leaf (call-args node))
- (call-analyze-known (call-proc node)))))
- ((1)
- (cond ((primop-ref? (call-proc node) primop/y)
- (destructure (((cont master) (call-args node)))
- (call-analyze-leaf cont)
- (destructure (((body-expr . label-exprs)
- (call-args (lambda-body master))))
- (let ((v (call-analyze-leaf body-expr)))
- (cond ((or (and (lambda-node? cont)
- (eq? (lambda-strategy cont)
- strategy/stack))
- (fx= v call-below/definitely))
- (walk call-analyze-leaf label-exprs)
- call-below/definitely)
- (else
- (do ((l label-exprs (cdr l))
- (val v (call-below-combine
- val
- (call-analyze-leaf (car l)))))
- ((null? l) val))))))))
- ((lambda-node? (call-proc node))
- (call-analyze-let node))
- (else
- (destructure (((exit . rest) (call-args node)))
- (walk call-analyze-leaf rest)
- (cond ((lambda-node? exit)
- (call-analyze-leaf exit))
- (else
- (call-analyze-known (call-proc node))))))))
- ((2)
- (destructure (((th el . rest) (call-args node)))
- (walk call-analyze-leaf rest)
- (call-below-combine (call-analyze-leaf th) (call-analyze-leaf el))))
- (else
- (let ((exits (call-exits node)))
- (do ((below? (call-analyze-leaf ((call-arg 1) node))
- (call-below-combine (call-analyze-leaf ((call-arg i) node))
- below?))
- (i 2 (fx+ i 1)))
- ((fx> i exits) below?)))))))
- (set (call-below? node) below?)
- below?))
-
- (define (call-analyze-let node)
- (iterate loop ((args (call-args node))
- (val call-below/never))
- (cond ((null? args)
- (let ((body-val (call-analyze-leaf (call-proc node))))
- (cond ((fx= body-val call-below/definitely)
- body-val)
- (else
- (call-below-combine val body-val)))))
- ((lambda-node? (car args))
- (loop (cdr args)
- (call-below-combine
- val
- (call-analyze-leaf (car args)))))
- (else
- (loop (cdr args) val)))))
-
- (define (call-analyze-known proc)
- (cond ((and (reference-node? proc)
- (variable-known (reference-variable proc)))
- => (lambda (l)
- (let ((cb (call-below? (lambda-body l))))
- (if (fixnum? cb) cb call-below/never))))
- (else call-below/never)))
-
-
- (let ((vec '#(#(0 1 1) #(1 1 1) #(1 1 2))))
- (define (call-below-combine x y)
- (vref (vref vec x) y)))
-